package com.icesoft.system.safe.interceptor;

import com.icesoft.framework.core.base.BaseAnnotationInterceptor;
import com.icesoft.framework.core.config.Cons;
import com.icesoft.framework.core.exception.BusinessException;
import com.icesoft.framework.core.util.D;
import com.icesoft.system.annotation.SafeRequest;
import com.icesoft.system.safe.config.SafeHttpServletRequest;
import com.icesoft.system.safe.filter.HeadSafeRequestFilter;
import com.icesoft.system.safe.filter.ParamSafeRequestFilter;
import com.icesoft.system.safe.filter.impl.TimeUnitNonceStrFilter;
import com.icesoft.system.safe.helper.RequestHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.TreeMap;

@Slf4j
@Component
@RequiredArgsConstructor
@Order(value = Ordered.HIGHEST_PRECEDENCE)
public class SafeRequestInterceptor extends BaseAnnotationInterceptor<SafeRequest> {

	private final TimeUnitNonceStrFilter timeUnitNonceStrFilter;

	private final List<ParamSafeRequestFilter> paramFilters;

	private final List<HeadSafeRequestFilter> headFilters;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, SafeRequest safeRequest) throws IOException {
		if (safeRequest == null || safeRequest.disable()) {
			return true;
		}

		long startTime = System.currentTimeMillis();
		request.setAttribute("requestStartTime", startTime);

		for (HeadSafeRequestFilter appFilter : headFilters) {
			if (!appFilter.headFilter(request, response)) {
				return false;
			}
		}

		TreeMap<String, String> paramMap;
		SafeHttpServletRequest bcRequest = (SafeHttpServletRequest) request.getAttribute(SafeHttpServletRequest.ATTR_NAME);
		try {
			paramMap = bcRequest.resolveParam();
		} catch (Exception e) {
			log.error("", e);
			throw new BusinessException(e.getMessage());
		}

		if (paramMap == null) {
			throw new BusinessException("json格式错误");
		}

		String url = RequestHelper.getRequestUrl(request);
		String remoteIP = RequestHelper.getRemoteIP(request);
		String method = request.getMethod();
		String debug = "\n" +
				"| SafeRequest \n" +
				"| id : " + startTime + "\n" +
				"| 时间 : " + D.now(D.FORMAT_DATETIME_Y4MDHMS) + "\n" +
				"| 请求 : " + url + "\n" +
				"| method : " + method + "\n" +
				"| clientType : " + request.getHeader("clientType") + "\n" +
				"| versionCode : " + request.getHeader("versionCode") + "\n" +
				"| ip : " + remoteIP + "\n" +
				"| 加密参数 : " + bcRequest.getBody() + "\n" +
				"| 解密参数 : " + paramMap;
		log.debug(debug);

		if (!timeUnitNonceStrFilter.filter(bcRequest, response)) {
			log.debug("timeUnitNonceStr校验失败");
			throw new BusinessException("timeUnitNonceStr校验失败");
		}
		for (ParamSafeRequestFilter appFilter : paramFilters) {
			if (!appFilter.paramFilter(request, response, paramMap)) {
				throw new BusinessException("");
			}
		}
		request.setAttribute(Cons.REQUEST_RESOLVER_PARAM_MAP_NAME, paramMap);
		return true;
	}
}
